home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / dejagnu.lha / dejagnu-1.0.1 / expect / exp_tk.c < prev    next >
C/C++ Source or Header  |  1993-03-29  |  6KB  |  270 lines

  1. /* exp_tk.c - Tk event interface for Expect
  2.  
  3. Written by: Don Libes, NIST, 2/6/90
  4.  
  5. Design and implementation of this program was paid for by U.S. tax
  6. dollars.  Therefore it is public domain.  However, the author and NIST
  7. would appreciate credit if this program or parts of it are used.
  8.  
  9. */
  10.  
  11. /* Notes:
  12. I'm only a little worried because Tk does not check for errno == EBADF
  13. after calling select.  I imagine that if the user passes in a bad file
  14. descriptor, we'll never get called back, and thus, we'll hang forever
  15. - it would be better to at least issue a diagnostic to the user.
  16.  
  17. Another possible problem: Tk does not do file callbacks round-robin.
  18.  
  19. Another possible problem: Calling Create/DeleteFileHandler
  20. before/after every Tcl_Eval... in expect/interact could be very
  21. expensive.
  22.  
  23. */
  24.  
  25.  
  26. #include "exp_conf.h"
  27. #include <stdio.h>
  28. #include <errno.h>
  29.  
  30. #ifdef HAVE_PTYTRAP
  31. #  include <sys/ptyio.h>
  32. #endif
  33.  
  34. #include "tk.h"
  35.  
  36. #include "exp_global.h"
  37. #include "exp_command.h"    /* for struct f defs */
  38. #include "exp_event.h"
  39.  
  40. /* Tk_DoOneEvent will call our filehandler which will set the following vars */
  41. /* enabling us to know where and what kind of I/O we can do */
  42. /*#define EXP_SPAWN_ID_BAD    -1*/
  43. /*#define EXP_SPAWN_ID_TIMEOUT    -2*/    /* really indicates a timeout */
  44.  
  45. static int ready_fd = EXP_SPAWN_ID_BAD;
  46. static int ready_mask;
  47. static int default_mask = TK_READABLE | TK_EXCEPTION;
  48. #if 0
  49. #ifdef HAVE_PTYTRAP
  50. static int default_mask = TK_READABLE | TK_EXCEPTION;
  51. #else
  52. static int default_mask = TK_READABLE;
  53. #endif
  54. #endif
  55.  
  56. void exp_filehandler(clientData,mask)
  57. ClientData clientData;
  58. int mask;
  59. {
  60.     if (ready_fd == (int)clientData) {
  61.         Tk_DeleteFileHandler(ready_fd);
  62.         fs[ready_fd].armed = FALSE;
  63.     } else {
  64.     ready_fd = (int)clientData;
  65.     ready_mask = mask;
  66. }
  67. }
  68.  
  69. /*ARGSUSED*/
  70. void
  71. exp_timehandler(clientData)
  72. ClientData clientData;
  73. {
  74.     /* clientData == &timer_fired */
  75.     *(int *)clientData = TRUE;    
  76.  
  77.     /* old implementation */
  78.     /* ready_fd = EXP_SPAWN_ID_TIMEOUT; */
  79. }
  80.  
  81. #if 0
  82. void
  83. exp_disarm_event_handler(count,fds)
  84. int count;
  85. int *fds;
  86. {
  87.     int i;
  88.  
  89.     for (i=0;i<count;i++) {
  90.         Tk_DeleteFileHandler(fds[i]);
  91.     }
  92. }
  93.  
  94.  
  95. void
  96. exp_arm_event_handlers(count,fds)
  97. int count;
  98. int *fds;
  99. {
  100.     int i;
  101.     int flag = TK_WRITABLE;
  102.  
  103.     flag |= TK_EXCEPTION;
  104. #if 0
  105. #ifdef HAVE_PTYTRAP
  106.     flag |= TK_EXCEPTION;
  107. #endif
  108. #endif
  109.  
  110.     for (i=0;i<count;i++) {
  111.         Tk_CreateFileHandler(fds[i],flag,exp_filehandler,(ClientData)fds[i]);
  112.     }
  113. }
  114. #endif
  115.  
  116. void
  117. exp_event_disarm(fd)
  118. int fd;
  119. {
  120.     Tk_DeleteFileHandler(fd);
  121. }
  122.  
  123. /* returns status, one of EOF, TIMEOUT, ERROR or DATA */
  124. /*ARGSUSED*/
  125. int exp_get_next_event(interp,masters, n,master_out,timeout,key)
  126. Tcl_Interp *interp;
  127. int *masters;
  128. int n;            /* # of masters */
  129. int *master_out;    /* 1st ready master, not set if none */
  130. int timeout;        /* seconds */
  131. int key;
  132. {
  133.     static rr = 0;    /* round robin ptr */
  134.     int i;    /* index into in-array */
  135.  
  136.     int timer_created = FALSE;
  137.     int timer_fired = FALSE;
  138.     Tk_TimerToken timetoken;/* handle to Tk timehandler descriptor */
  139.  
  140.     for (;;) {
  141.         int m;
  142.         struct f *f;
  143.  
  144.         /* if anything has been touched by someone else, report that */
  145.         /* an event has been received */
  146.  
  147.         for (i=0;i<n;i++) {
  148.             rr++;
  149.             if (rr >= n) rr = 0;
  150.  
  151.             m = masters[rr];
  152.             f = fs + m;
  153.  
  154.             if (f->key != key) {
  155.                 f->key = key;
  156.                 f->force_read = FALSE;
  157.                 *master_out = m;
  158.                 return(EXP_DATA_OLD);
  159.             } else if ((!f->force_read) && (f->size != 0)) {
  160.                 *master_out = m;
  161.                 return(EXP_DATA_OLD);
  162.             }
  163.         }
  164.  
  165.         if (!timer_created) {
  166.             if (timeout >= 0) {
  167.                 timetoken = Tk_CreateTimerHandler(1000*timeout,
  168.                         exp_timehandler,
  169.                         (ClientData)&timer_fired);
  170.                 timer_created = TRUE;
  171.             }
  172.         }
  173.  
  174.         for (;;) {
  175.             extern int fd_max;
  176.             int j;
  177.  
  178.             /* make sure that all fds that should be armed are */
  179.             for (j=0;j<n;j++) {
  180.                 int k = masters[j];
  181.  
  182.                 if (!fs[k].armed) {
  183.                     Tk_CreateFileHandler(k,default_mask,
  184.                                  exp_filehandler,
  185.                                  (ClientData)k);
  186.                     fs[k].armed = TRUE;
  187.                 }
  188.             }
  189.  
  190.             Tk_DoOneEvent(0);    /* do any event */
  191.             if (timer_fired) return(EXP_TIMEOUT);
  192.             if (ready_fd == EXP_SPAWN_ID_BAD) continue;
  193.  
  194.             /* if it was from something we're not looking for at */
  195.             /* the moment, ignore it */
  196.             for (j=0;j<n;j++) {
  197.                 if (ready_fd == masters[j]) goto found;
  198.             }
  199.             /* not found */
  200.             Tk_DeleteFileHandler(ready_fd);
  201.             fs[ready_fd].armed = FALSE;
  202.             ready_fd = EXP_SPAWN_ID_BAD;
  203.             continue;
  204.         found:
  205.             *master_out = ready_fd;
  206.             ready_fd = EXP_SPAWN_ID_BAD;
  207.  
  208.             if (timer_created) Tk_DeleteTimerHandler(timetoken);
  209.  
  210. /*#ifdef HAVE_PTYTRAP*/
  211.             if (ready_mask & TK_EXCEPTION) {
  212. #ifndef HAVE_PTYTRAP
  213.                 return(EXP_EOF);
  214. #else
  215.                 struct request_info ioctl_info;
  216.                 if (ioctl(*master_out,TIOCREQCHECK,&ioctl_info) < 0) {
  217.                     exp_debuglog("ioctl error on TIOCREQCHECK: %d", errno);
  218.                     return(TCL_ERROR);
  219.                 }
  220.                 if (ioctl_info.request == TIOCCLOSE) {
  221.                     return(EXP_EOF);
  222.                 }
  223.                 if (ioctl(*master_out, TIOCREQSET, &ioctl_info) < 0) {
  224.                     exp_debuglog("ioctl error on TIOCREQSET after ioctl or open on slave: %d", errno);
  225.                     }
  226.                 /* presumably, we trapped an open here */
  227.                 continue;
  228. #endif
  229.             }
  230. /*#endif *//*HAVE_PTYTRAP*/
  231.             return(EXP_DATA_NEW);
  232.         }
  233.     }
  234. }
  235.  
  236. void
  237. exp_usleep(usec)
  238. long usec;
  239. {
  240.     int timer_fired = FALSE;
  241.  
  242.     Tk_CreateTimerHandler(usec/1000,exp_timehandler,(ClientData)&timer_fired);
  243.  
  244.     while (1) {
  245.         Tk_DoOneEvent(0);
  246.         if (timer_fired) return;
  247.  
  248.         if (ready_fd == EXP_SPAWN_ID_BAD) continue;
  249.         
  250.         Tk_DeleteFileHandler(ready_fd);
  251.         fs[ready_fd].armed = FALSE;
  252.         ready_fd = EXP_SPAWN_ID_BAD;
  253.     }
  254. }
  255.  
  256. static void
  257. exp_event_exit_real(interp)
  258. Tcl_Interp *interp;
  259. {
  260.     Tcl_Eval(interp,"destroy .",0,(char **)NULL);
  261. }
  262.  
  263. /* set things up for later calls to event handler */
  264. void
  265. exp_init_event()
  266. {
  267.     exp_event_exit = exp_event_exit_real;
  268. }
  269.  
  270.